use serde::Deserialize;
use std::fs::File;
use std::io::{self, BufReader};
use std::path::PathBuf;
use log::info;

use crate::utils::get_executable_dir;

// Configuration constants
pub const DEFAULT_CONFIG_PATH: &str = "config.json";
pub const DEFAULT_APP_NAME: &str = "PkgTools GUI";
pub const DEFAULT_PKGTOOL: &str = "pkgtool.exe";
pub const DEFAULT_LOG_LEVEL: &str = "info";
pub const DEFAULT_HOST: &str = "192.168.1.10";
pub const DEFAULT_PORT: u16 = 22;

#[derive(Deserialize, Clone)]
pub struct AppConfig{
    pub app_name: String,
    pub log_level: String,
}

impl Default for AppConfig {
    fn default() -> Self {
        Self {
            app_name: String::from(DEFAULT_APP_NAME),
            log_level: String::from(DEFAULT_LOG_LEVEL),
        }
    }
}

#[derive(Deserialize, Clone)]
pub struct NetworkConfig{
    pub host: String,
    pub port: u16,
    #[serde(default)]
    pub connection_type: String,
    #[serde(default)]
    pub mock_connection: bool,
}

impl Default for NetworkConfig {
    fn default() -> Self {
        Self {
            host: String::from(DEFAULT_HOST),
            port: DEFAULT_PORT,
            connection_type: String::from("tcp"),
            mock_connection: false,
        }
    }
}

#[derive(Deserialize, Clone)]
pub struct ToolConfig{
    pub pkgtool: String,
}

impl Default for ToolConfig {
    fn default() -> Self {
        Self {
            pkgtool: String::from(DEFAULT_PKGTOOL),
        }
    }
}

#[derive(Deserialize, Clone)]
pub struct Config {
    #[serde(flatten)]
    pub app: AppConfig,
    #[serde(flatten)]
    pub network: NetworkConfig,
    #[serde(flatten)]
    pub tool: ToolConfig,
}

impl Default for Config {
    fn default() -> Self {
        Self {
            app: AppConfig::default(),
            network: NetworkConfig::default(),
            tool: ToolConfig::default(),
        }
    }
}

impl Config {
    pub fn load() -> Self {
        if let Some(exe_dir) = get_executable_dir() {
            let config_path = exe_dir.join(DEFAULT_CONFIG_PATH);
            if let Ok(mut config) = read_config(config_path.to_str().unwrap_or(DEFAULT_CONFIG_PATH)) {
                // Check if pkgtool path is absolute
                let pkgtool_path = PathBuf::from(&config.tool.pkgtool);
                if !pkgtool_path.is_absolute() {
                    // Prepend the executable directory to the pkgtool path
                    config.tool.pkgtool = exe_dir
                        .join(pkgtool_path)
                        .to_str()
                        .unwrap_or(&config.tool.pkgtool)
                        .to_string();
                }
                return config;
            } else {
                info!("无法加载配置文件，使用默认配置");
            }
        }
        Config::default()
    }
}

fn read_config(file_path: &str) -> io::Result<Config> {
    let file = File::open(file_path)?;
    let reader = BufReader::new(file);
    serde_json::from_reader(reader)
        .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
}